import { Request } from 'express';
import * as crypto from 'crypto';

/**
 * 设备指纹工具类
 * 用于生成和验证设备唯一标识
 */
export class DeviceFingerprintUtil {
  /**
   * 生成设备指纹
   * 基于 User-Agent、Accept-Language 等浏览器特征
   */
  static generate(request: Request): string {
    const userAgent = request.headers['user-agent'] || '';
    const acceptLanguage = request.headers['accept-language'] || '';
    const acceptEncoding = request.headers['accept-encoding'] || '';

    // 组合多个特征生成唯一标识
    const rawFingerprint = `${userAgent}|${acceptLanguage}|${acceptEncoding}`;

    // 使用 SHA256 哈希生成固定长度的指纹
    return crypto.createHash('sha256').update(rawFingerprint).digest('hex');
  }

  /**
   * 获取客户端 IP 地址
   * 支持代理和负载均衡场景
   */
  static getIpAddress(request: Request): string {
    const forwardedFor = request.headers['x-forwarded-for'];
    const realIp = request.headers['x-real-ip'];

    if (forwardedFor) {
      // x-forwarded-for 可能包含多个 IP，取第一个
      return Array.isArray(forwardedFor)
        ? forwardedFor[0]
        : forwardedFor.split(',')[0].trim();
    }

    if (realIp) {
      return Array.isArray(realIp) ? realIp[0] : realIp;
    }

    return request.ip || request.socket.remoteAddress || 'unknown';
  }

  /**
   * 获取 User Agent
   */
  static getUserAgent(request: Request): string {
    return request.headers['user-agent'] || 'unknown';
  }

  /**
   * 验证两个 IP 是否在同一区域
   * 简化实现：检查前3段是否相同（同一子网）
   * 生产环境建议使用 IP 地理位置库（如 MaxMind GeoIP）
   */
  static isSameRegion(ip1: string, ip2: string): boolean {
    if (ip1 === ip2) return true;

    // IPv4 简单比对
    const segments1 = ip1.split('.');
    const segments2 = ip2.split('.');

    if (segments1.length === 4 && segments2.length === 4) {
      // 比较前3段（C类网段）
      return (
        segments1[0] === segments2[0] &&
        segments1[1] === segments2[1] &&
        segments1[2] === segments2[2]
      );
    }

    // IPv6 或其他情况，暂不实现
    return false;
  }

  /**
   * 计算风险评分
   */
  static calculateRiskScore(params: {
    currentIp: string;
    lastKnownIp: string;
    currentDevice: string;
    lastKnownDevice: string;
    refreshCount: number;
  }): number {
    let score = 0;

    // IP 完全不同
    if (params.currentIp !== params.lastKnownIp) {
      score += 30;

      // IP 不在同一区域
      if (!this.isSameRegion(params.currentIp, params.lastKnownIp)) {
        score += 20;
      }
    }

    // 设备指纹不同（高风险）
    if (params.currentDevice !== params.lastKnownDevice) {
      score += 40;
    }

    // 短时间内频繁刷新（可能是脚本攻击）
    if (params.refreshCount > 10) {
      score += 30;
    } else if (params.refreshCount > 5) {
      score += 15;
    }

    return score;
  }
}
